#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <arpa/inet.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <pthread.h>
#include <termios.h>//串口
#include <sys/stat.h>
#include <fcntl.h>
//高玉浩
#define N 32
#include "data_global.h"
#include <sys/msg.h>
//高玉浩
#include "sem.h"
#define SEND_OK 0xAA
typedef struct{
    uint8_t head[3]; //标识位
	uint8_t type;   //数据仓库
	uint8_t snum;    //仓库编号

	uint8_t temp[2];  //温度
	uint8_t hum[2];   //湿度
	uint8_t x;        //三轴信息
	uint8_t y;       
	uint8_t z;
	uint32_t ill;    //光照
	uint32_t bet;    //电池电量
	uint32_t adc;    //电位器信息
}MSG;
//高玉浩
struct msg{
    long type;
	long msgtype;
	unsigned char text[N];
}M0;
//高玉浩
typedef struct linklist{
    MSG data;
    struct linklist *next;
}linklist_t;

linklist_t *create_linklist(void)
{
    linklist_t *l = (linklist_t *)malloc(sizeof(linklist_t));//创建头结点
    l->next = NULL;
	return l;
}

int  is_empty_linklist(linklist_t *l) //判断；链表是否为空
{
    return(l->next == NULL);
}

int insert_linklist(linklist_t *l, MSG x)//添加结点
{
    linklist_t *node = (linklist_t *)malloc(sizeof(linklist_t));
	node->data = x;
	node->next = NULL;
	linklist_t *p = l;
	while(p->next != NULL)
	{
	    p = p->next;
	}
	p->next = node;
}

MSG msg;
MSG *pmsg;
int semid;
pthread_mutex_t lock0, lock1;//定义锁的名字
pthread_cond_t condition;

void serial_init(int fd)
{
    struct termios options;
	tcgetattr(fd, &options);
	options.c_cflag |= ( CLOCAL | CREAD);
	options.c_cflag &= ~CSIZE;
	options.c_cflag &= ~CRTSCTS;
	options.c_cflag |= CS8;
	options.c_cflag &= ~CSTOPB;
	options.c_iflag |= IGNPAR;
	options.c_iflag &= ~(ICRNL | IXON);
	options.c_oflag = 0;
	options.c_lflag = 0;

	cfsetispeed(&options, B115200);
	cfsetispeed(&options, B115200);
	tcsetattr(fd, TCSANOW, &options);
}

void *pthread_read_m0_func(void *arg)
{
    int dev_uart_fd;
	if((dev_uart_fd = open("/dev/ttyUSB0", O_RDWR)) < 0)
	{
	    perror("open uart err");
		return (void *)-1;
	}
	serial_init(dev_uart_fd);//串口初始化
	while(1)
	{
	    pthread_mutex_lock(&lock0);
		read(dev_uart_fd, &msg, sizeof(MSG));
	//*/
		pthread_mutex_unlock(&lock0);
	}
	return NULL;
}

void *pthread_shm_func(void *arg)
{
    while(1)
	{
	    sem_p(semid, 0);
		*pmsg = msg;
		sem_v(semid, 0);
	}
	return NULL;
}


//高玉浩
void *pthread_uart_cmd_func(void *arg)
{
	key_t key;
	int msgid;
	M0 m0;
	int uart_cmd_fd;
	if((key = ftok("/app", 'g')) < 0)
	{
		perror("fail to ftok cmd");
		exit(1);
	}
	if((msgid = msgget(key, 0666)) < 0)
	{
		perror("fail to msgget");
		exit(1);
	}
	if((ssize_t size = msgrcv(msgid, m0, sizeof(m0)-sizeof(long), 0)) < 0)
	{
		perror("fail to msgrcv");
		exit(1);
	}
	else
	{
		if((uart_cmd_fd = open("/dev/ttyUSB0", O_RDWR)) < 0)
		{
			perror("fail to open cmd");
			exit(1);
		}
		if(m0.msgtype == 4L)
		{
			switch(m0.text[N])
			{
				//*/
	//*/
            case:MSG_M0_FAN__OFF
	             write(uart_cmd_fd, "0x80", 1);
	             break;
            case:MSG_M0_FAN__ON1
	             write(uart_cmd_fd, "0x81", 1);
	             break;
            case:MSG_M0_FAN__ON2
	             write(uart_cmd_fd, "0x82", 1);
	             break;
            case:MSG_M0_FAN__ON3
	             write(uart_cmd_fd, "0x83", 1);
	             break;
            case:MSG_M0_BEEP_OFF
	             write(uart_cmd_fd, "0x90", 1);
	             break;
            case:MSG_M0_BEEP_ON
	             write(uart_cmd_fd, "0x91", 1);
	             break;
            case:MSG_M0_BEEP_AU_OFF
	             write(uart_cmd_fd, "0x92", 1);
	             break;
            case:MSG_M0_BEEP_AU_ON
	             write(uart_cmd_fd, "0x93", 1);
	             break;
            case:MSG_M0_LED_ON
	             write(uart_cmd_fd, "0xa0", 1);
	             break;
            case:MSG_M0_LED_OFF
	             write(uart_cmd_fd, "0xa1", 1);
	             break;
            case:MSG_M0_SEG_ON
	             write(uart_cmd_fd, "0xb0", 1);
	             break;
            case:MSG_M0_SEG_OFF
	             write(uart_cmd_fd, "0xb1", 1);
	             break;
			}
		}
	}

}
//高玉浩


void *pthread_linklist_func(void *arg)
{
    linklist_t *l = create_linklist();
	while(1)
	{
	    pthread_mutex_lock(&lock0);
		insert_linklist(l, msg);
		pthread_mutex_unlock(&lock0);
	}
}
int main(int argc, const char *argv[])
{
	pthread_t pthread_read_m0, pthread_shm, pthread_linklist, pthread_uart_cmd;
	int shmid;
	key_t key;
	key = ftok("/", 'a');
	if(key < 0)
	{
	    perror("fail to ftok");
		exit(-1);
	}

	fisrt_init_sem(&semid, &key);//初始化信号量
	init_sem(semid, 0, 1);
	pthread_mutex_init(&lock0, NULL);//初始化互叱锁
	pthread_mutex_init(&lock1, NULL);//初始化互叱锁
	//pthread_mutex_init(&condition, NULL);//初始化条件变量

	shmid = shmget(key, sizeof(MSG), IPC_CREAT | IPC_EXCL | 0777);
	if(shmid < 0)
	{
	    if(errno == EEXIST)
		{
		    shmid = shmget(key, 0, 0777);
		}
		else
		{
		    perror("fail to shmget");
			exit(-1);
		}
	}
	if((pmsg = (MSG *)shmat(shmid, NULL, 0)) == (MSG *)-1)
	{
	    perror("fail to shmat");
		exit(-1);
	}
	//映射完共享内存开始创建线程
    if(pthread_create(&pthread_read_m0, NULL, pthread_read_m0_func, NULL) != 0)
	{
	    perror("fail to pthread_create");
		exit(-1);
	}
	sleep(1);
	if(pthread_create(&pthread_shm, NULL, pthread_shm_func, NULL) != 0)
	{
	    perror("fail to pthread_create");
		exit(-1);
	}
	if(pthread_create(&pthread_linklist, NULL, pthread_linklist_func, NULL) != 0)
	{
	    perror("fail to pthread_create");
		exit(-1);
	}
	//高玉浩 M0线程
	if(pthread_create(&pthread_uart_cmd, NULL, pthread_uart_cmd_func, NULL) != 0)
	{
	    perror("fail to pthread_create");
		exit(-1);
	}
	//高玉浩
	if(p)
	pause();
	return 0;
}
